當同個時間點,生產者一邊在產生資源,並將其填入 Queue ;另一邊,消費者從 Queue 中取出資源,以利後續處理。
一來一往之處,如果沒有同步的機制,極有可能造成存取的錯亂,嚴重影響資料的正確性。
首先上場的是 .Net  Lock 機制,利用指定指定物件的互斥鎖定,以確保鎖定期間,鎖定範圍內的陳述式不受其他執行緒影響,正常的完成任務,直到離開鎖定範圍。

在上面的示意圖中,兩名生產者與一名消費者,先後存取 Queue,在 Lock 機制的保護下,Queue 會依據請求時間的先後,依序完成 producer 1、Customer 1、 Producer 2 的存取動作。
在 lock 的使用上,MSDN 之中,也特別提到同步處理執行緒對共用資源的存取時,請鎖定專用物件執行個體。
也就是用來用 lock 的指定物件,盡可能使用專門的物件。
private readonly object _lock = new object ();
lock(_lock)
{
    //	要確保資料正確性旳程式區塊
}
同時為避免死鎖(deadlock) 或鎖定爭用(lock contention) 的情況發生,請避免...
this 、Type 類別與字串。如果有興趣進一步了解,可以進一步閱讀 說說lock到底鎖誰? 這篇文章。
接著,我們繼承前面實作的 Queue ,將其加上 Lock 機制。
public class LockQueue<T> : Queue<T> 
{
    private readonly object _lock = new object ();
    public override void Enqueue (T item) 
    {
        lock (_lock) { base.Enqueue (item); }
    }
    public override bool IsEmpty => { lock (_lock) { base.IsEmpty; } }
    public T Dequeue () 
    {
        lock (_lock) { return base.Dequeue (); }
    }
}
測試程式如下:
 private static void Main(string[] args)
 {
     var queue = new Queue<int>();
     Random rand = new Random();
     var timesLimit = 10;
     var producer = Task.Run(() =>
       {
           var times = timesLimit;
           while (times-- != 0)
           {
               var item = rand.Next(500);
               System.Console.WriteLine($"Enqueue: {item}");
               queue.Enqueue(item);
               Thread.Sleep(100);
           }
           System.Console.WriteLine("produce end.");
       });
     var consumer1 = Task.Run(() => { Program.Consumer(queue); });
     var consumer2 = Task.Run(() => { Program.Consumer(queue); });
     System.Console.Read();
 }
 private static void Consumer<T>(Queue<T> queue)
 {
     while (true)
     {
         if (queue.IsEmpty)
         {
             Thread.Sleep(10);
             continue;
         }
         var item = queue.Dequeue();
         System.Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] Dequeue: {item}");
         Thread.Sleep(100);
     }
 }